package org.webscale.util;

/*
 * PropertyResolver.java
 *
 * Created on April 16, 2002, 12:00 PM
 */

import java.util.*;
/**
 * Utility Class to resolve various formats use in property files.
 * @author  niraj
 * @version
 */
public final class PropertyResolver {
	
	private PropertyResolver(){
	}

	private static final String TRAIL = "$trail$";

	/**
		 * will convert a structure
		 * <br> input
		 * <br>
		 * mapper.datamapper.default.1 = aaaa <br>
		 * mapper.datamapper.default.2 = bbbb <br>
		 * mapper.datamapper.default.3 = cccc <br>
		 * mapper.datamapper.ser.1 = a2a2 <br>
		 * mapper.datamapper.ser.2 = b2b2 <br>
		 * 
		 * to <br>
		 *
		 * a Map
		 *  = { key =default , value = {aaaa, bbbb , cccc} ,key = ser , value ={a2a2, b2b2});
		 *value is an Ordered List
		 * argument will look like this <br>
		 *<br> PropertyResolver.Resolve(prop , "mapper.datamapper" , 50);
		 **/
	public static Map<String, List<String>> resolveSequencedPropertiesAsMap(Properties prop,String startKey, int maxNumber) {
		HashMap map = new HashMap();
		List<String> subKeyList = new ArrayList<String>();
		System.out.println(" Inputs " + startKey + " Prop " + prop);
		Enumeration enum1 =prop.keys();
		while(enum1.hasMoreElements()){
			String key = (String)enum1.nextElement();
			if(key.startsWith(startKey)){
				//String subKey = key.substring(0 , key.lastIndexOf("."));
				String subKey = key.substring(startKey.length() + 1 , key.lastIndexOf("."));
				//subKey = startKey + "." +subKey; 
				System.out.println(" SUB KEY "  + subKey);
				if(!subKeyList.contains(subKey)){
					System.out.println(" CONTEAIN "  + subKey);
					subKeyList.add(subKey);
				}
			}
		}
		
		System.out.println("sub ley List  " + subKeyList);
		Iterator it = subKeyList.iterator();
		while(it.hasNext()){
			String subKey = (String)it.next();
			String newStartKey = startKey + "." + subKey;
			
			List list = resolveSequencedProperties(prop ,newStartKey , 50);
			map.put(subKey , list);
		}
		return map;
		
	}

	/**
	 * will convert a structure
	 * <br> input
	 * <br>
	 * mapper.datamapper.default.1 = aaaa <br>
	 * mapper.datamapper.default.2 = bbbb <br>
	 * mapper.datamapper.default.3 = cccc <br>
	 * to <br>
	 *
	 * a List
	 *  = { key =default , value = {aaaa, bbbb , cccc});
	 *value is an Ordered List
	 * argument will look like this <br>
	 *<br> PropertyResolver.Resolve(prop , "mapper.datamapper" , 50);
	 */
	public static List resolveSequencedProperties(
		Properties prop,
		String startKey,
		int maxNumber) {
		String[] propArray = new String[maxNumber];
		Enumeration enum1 = prop.keys();
		while (enum1.hasMoreElements()) {
			String key = (String) enum1.nextElement();
			String value = prop.getProperty(key);
			//            System.out.println(" ");
			//   System.out.print(" Key= " + key + " Value = " + value );
			int i = key.lastIndexOf(".");
			if (i < 1)
				continue;

			String endNumber = key.substring(i + 1);
			int num = 0;
			try {
				num = Integer.parseInt(endNumber.trim());
			} catch (Exception ex) {
				continue;
			}

			//     System.out.print(" *** END number =" + num);
			if (key.startsWith(startKey)) {
				propArray[num] = value;

			}
		}

		List list = Arrays.asList(propArray);
		list = removeAllNulls(list);
		return list;
	}

	/**
	 * will convert a structure
	 * <br> input
	 * <br>
	 * mapper.datamapper.interface.1 = aaaa <br>
	 * mapper.datamapper.impl.1 = bbbb <br>
	 * mapper.datamapper.interface.2 = a2a2 <br>
	 * mapper.datamapper.impl.2 = b2b2 <br>
	 * 
	 * to <br>
	 *
	 * a List of Properties <br>
	 *  = { Prop1{interface = aaaa, imple = bbbb} ,Prop2{interface= a2a2, impl = b2b2});
	 *
	 * argument will look like this <br>
	 *<br> PropertyResolver.Resolve(prop , "mapper.datamapper" , 50);
	 *
	 */

	public static List resolveSequencedAndGroupedProperties(
		Properties prop,
		String startKey,
		int maxNumber) {

		Properties[] propArray = new Properties[maxNumber];
		Enumeration enum1 = prop.keys();
		while (enum1.hasMoreElements()) {
			String key = (String) enum1.nextElement();
			String value = prop.getProperty(key);
			//		System.out.println(" ");
			//   System.out.print(" Key= " + key + " Value = " + value );
			int i = key.lastIndexOf(".");
			if (i < 1)
				continue;

			String endNumber = key.substring(i + 1);
			int num = 0;
			try {
				num = Integer.parseInt(endNumber.trim());
			} catch (Exception ex) {
				continue;
			}

			//     System.out.print(" *** END number =" + num);
			if (key.startsWith(startKey)) {
				int lengthOfStartKey = 0;

				if (startKey.endsWith("."))
					lengthOfStartKey = startKey.length() - 1;
				else {
					lengthOfStartKey = startKey.length();
				}

				String innerKey = key.substring(lengthOfStartKey + 1, i);
				//  	System.out.print(" *** Inner key = " + innerKey); 

				try {
					Properties innerProp = (Properties) propArray[num];
					if (innerProp == null)
						throw new IndexOutOfBoundsException();
					innerProp.put(innerKey, value);
					//	System.out.print(" ** FOUND inner Prop at " + num); 
				} catch (IndexOutOfBoundsException ioe) {
					Properties newInnerProp = new Properties();
					newInnerProp.put(innerKey, value);
					propArray[num] = newInnerProp;
					//	  System.out.print(" *** Property added at " + num); 

				}

			}

		}

		List list = Arrays.asList(propArray);
		list = removeAllNulls(list);
		return list;
	}

	private static List removeAllNulls(List list) {

		ArrayList alist = new ArrayList();
		for (int i = 0; i < list.size(); i++) {
			Object obj = list.get(i);
			if (obj == null) {
				continue;
			}
			alist.add(obj);
		}

		return alist;
	}

	/**
	 * will convert a structure
	 * <br> input
	 * <br>
	 * eorion.service.1 = aaaa <br>
	 * eorion.ao.1 = ssss <br>
	 * eorion.delegate.1 = aaaa
	 * to <br>
	 *
	 * a HashMap of <br>
	 * service = { ao = ssss , delegate = aaaa};
	 *
	 * argument will look like this <br>
	 *<br> PropertyResolver.Resolve(prop , "service" , "eorion");
	 *
	 */

	public static Map resolve(
		Properties prop,
		String mapKey,
		String startKey) {
		Enumeration enum1 = prop.keys();
		HashMap map = new HashMap();
		while (enum1.hasMoreElements()) {
			String key = (String) enum1.nextElement();
			if (key.startsWith(startKey + "." + mapKey)) {
				String tmp = new String(startKey + "." + mapKey + ".");

				String trail = key.substring(tmp.length());
				Properties tprop = new Properties();
				tprop.setProperty(TRAIL, trail);
				map.put(prop.get(key), tprop);
			}
		}

		ArrayList alist = new ArrayList(map.keySet());
		for (int y = 0; y < alist.size(); y++) {

			String theMapKey = (String) alist.get(y);
			Properties tprop = (Properties) map.get(theMapKey);
			String trail = tprop.getProperty(TRAIL);
			map.put(alist.get(y), subProperties(prop, startKey, trail));

		}
		return map;
	}


		/**
		 * will convert a structure
		 *	 stubs.input.parser.simple=com.sss.s.s.s.s
		 *   stubs.input.parser.parserx=com.sss.s.s.s.s
		 *   to a Properties prop = {simple ,com.sss.s.s.s.s} , {parserx ,com.sss.s.s.s.s) 
		 */
	
	public static java.util.Properties subProperties(Properties prop,String start){
		Properties aprop = new Properties();
		List keys = subList(prop, start + ".", "");
		for (int i = 0; i < keys.size(); i++) {
			String str = (String)keys.get(i);
			if(str.startsWith("."))
			    str = str.substring(1);
				aprop.setProperty(str, prop.getProperty(start + "." + keys.get(i)));
			}
		
		return aprop;
	}
	


	
	public static java.util.Properties subProperties(
		Properties prop,
		String start,
		String trail) {
		Properties aprop = new Properties();
		List keys = subList(prop, start + ".", "." + trail);

		for (int i = 0; i < keys.size(); i++) {
			aprop.setProperty(
				(String) keys.get(i),
				prop.getProperty(start + "." + keys.get(i) + "." + trail));
		}
		return aprop;

	}

	/**
	 * Method subList.
	 * @param prop
	 * @param start
	 * @param trail
	 * @return List
	 */
	public static List subList(Properties prop, String start, String trail) {
		ArrayList list = new ArrayList();
		Enumeration enum1 = prop.keys();
		while (enum1.hasMoreElements()) {
			String str = (String) enum1.nextElement();
			if (str.startsWith(start) && str.endsWith(trail)) {
				str = str.substring(start.length(), str.lastIndexOf(trail));
				list.add(str);
			}
		}
		return list;

	}

	/**
	 * Method getValue.
	 * @param inmap
	 * @param key1
	 * @param key2
	 * @return String
	 */
	public static String getValue(Map inmap, String key1, String key2) {
		return ((Properties) inmap.get(key1)).getProperty(key2);
	}

	/** 
	 * Method main.
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			/*
			InputStream is =
				PropertyResolver.class.getClassLoader().getResourceAsStream(
					"resources/properties/stubconfig.properties");
			Properties prop = new Properties();
			prop.load(is);
			*/
			Properties prop = new Properties();
			prop.setProperty("stubs.input.parser.simple" , "VALUE1");
			prop.setProperty("stubs.input.parser.parser" , "VALUE2");
			Properties out = PropertyResolver.subProperties(prop , "stubs.input.parser");
			System.out.println(" RESULT " + out);
			
			//Map map = PropertyResolver.resolveSequencedPropertiesAsMap(prop , "struts.filter" , 10);
			//System.out.println(" RESULT " + map);
			/*
			List list =
				PropertyResolver.resolveSequencedProperties(
					prop,
					"initialisable.system.impl",
					50);
					
			System.out.println(" RESULT " + list.size());
			System.out.println(" Elements ");
			for (int i = 0; i < list.size(); i++) {
				System.out.println("Element num " + i + list.get(i));
			}
			
			*/
		} catch (Exception ex) {
			ex.printStackTrace();
		}

	}

    /**
     * This method will take the default properties and replaces those properties
     * that are overriden.
     *
     * <br> input
     * <br>
     * eorion.ao.default = bbbb <br>
     * eorion.service.1 = aaaa <br>
     * eorion.delegate.1 = aaaa
     * eorion.ao.1 = aaaa <br>
     * to <br>
     *
     * a HashMap of <br>
     * service = { ao = bbbb , delegate = aaaa};
     *
     * argument will look like this <br>
     *<br> PropertyResolver.Resolve(prop , "service" , "eorion", defaultProp);
     *
     * @param prop          Source properties.
     * @param mapKey        the map key value. In the above example 'service'.
     * @param startKey      The start key. In the above example 'eorion'.
     * @param defaultProps  The default properties required.
     *
     * @return  Returns required properties.
     */
    public static Map resolve(Properties prop, String mapKey, String startKey, Properties defaultProps) {
        Enumeration enum1 = prop.keys();
        Map map = new HashMap();
        String key = null;
        String tmp = null;
        String trail = null;
        Properties tprop = null;

        while (enum1.hasMoreElements()) {
            key = (String)enum1.nextElement();
            if (key.startsWith(startKey + "." + mapKey)) {
                tmp = new String(startKey + "." + mapKey + ".");

                trail = key.substring(tmp.length());
                tprop = new Properties();
                tprop.setProperty(TRAIL, trail);
                map.put(prop.get(key), tprop);
            }
        }

        List alist = new ArrayList(map.keySet());
        Properties newProps = null;

        for (int y = 0; y < alist.size(); y++) {
            newProps = new Properties();
            key = (String)alist.get(y);
            tprop = (Properties)map.get(key);
            trail = tprop.getProperty(TRAIL);

            newProps.putAll(defaultProps);
            newProps.putAll(subProperties(prop, startKey, trail));
            map.put(alist.get(y), newProps);
        }

        return map;
    }
}